
//1.什么是函数
//函数就是子程序，是一个大型程序中的某部分代码，由一个或者多个语句块组成。它负责完成某项特定的任务。相较于其他代码具备相对的独立性。
//一般会有输入参数并有返回值，提供对过程的封装和细节的隐藏。这些代码块通常被击中为软件库


//2.函数的分类
//(1)库函数   
// 常用的库函数：IO函数、字符串操作函数、内存操作函数、时间/日期函数、数学函数、其他库函数
//#define _CRT_SECURE_NO_WARNINGS 1
//#include<stdio.h>
//#include<string.h>
//int main()
//{
//	char ch[40] = { "test" };
//	char ch1[30] = { "zheliyouhenduo" };
//	strcpy(ch, ch1);//将ch1中的内容拷贝一份到ch中,会连带着ch的\0也一起拷贝进去，并且，拷贝之后，ch未覆盖的内容仍然存在
//	for (int i = 0; ch[i]; i++)
//	{
//	printf("%c\n", ch[i]);//这里的拷贝是将ch1的所有字符包括ch1字符的\0也拷贝了。但是ch数组中原来的字符其余位置还是存在字符。
//	                       //ch1的\0也占用了一个字符
//                         //要考虑内存溢出的情况，也就是被拷贝的数组(ch1)的长度要小于ch的长度，否则会报错
//                         
//	}
//	return 0;
//}





//memory-记忆，在c语言中叫内存。set-设置   >>>memset-内存设置，这个是一个函数
//(1)void *memset(void *str,int c, size_t n)>>>memset(*str,c,n) 复制字符 c（一个无符号字符）到参数 str 所指向的字符串的前 n 个字符。
//参数中的int c在实际参数的形式可以写成 'c' 这样的形式，当然也可以写成数字，如果写成数字就会转变为这个数字对应的ascll字符来进行天聪
// 
//(2)str:指要填充的内存块，也就是字符地址。常见的是数组，数组的本质就是地址。    
//   
// (3)c:将要填充到所指向地址的内容，只是一个字符,以整型（int）的方式进行传递，但是函数在填充内存块时是使用该值的无符号字符形式。
// 
//(4)n:要被设置为c值得字符个数，按原来的字符串顺序进行排列的
// 
//(5)该值返回一个指向存储区str的指针。          -----这个存储区一般指的的是数组这种地址
// 
//#include<stdio.h>
//#include<memory.h>
//int main()
//{
//	char arr[] = "hello word";
//	memset(arr, '*', 5);//这个空间的前五个字节都变成*这个字符   ***** word             只是将前五个进行改变，并不会将全部的字符串覆盖成为只有这五个*****
//                            //只能针对初始化过的数组，并且只能重写设置字符。不能用作字符串
//	printf("%s\n", arr);
//	return 0;
//}
// 补充：这个函数并不会检查第一个参数str的有效性，也不会检查 n 的长度是不是有效的，所以调用的时候需要调用者自己注意




//(2)自定义函数             ---其实就是我们自己设计的程序
//自定义函数和库函数一样，有函数名，返回值类型，和函数参数。但是不一样的是这些都是我们自己来设计。这给程序员一个很大的发挥空间

//实际参数：可以是变量，常量,表达式，函数等，但必须是一个确定的值

//形式参数：因为形式参数只有在函数被调用的过程中才实例化（分配内存单元）。形式参数当函数调用完之后就自动销毁了。形式参数只在函数中有用
//#include<stdio.h>//
//int jiaohuan(int x, int y)//形式参数这里也会有自己的独立的空间和地址。和传入的实参的地址并不相同
//{
//	int n = x;
//	x = y;
//	y = n;
//	return x,  y;
//}
//int main()
//{
//	int a = 20;
//	int b = 30;
//	jiaohuan(a,b);
//	printf("a交换后的值为：%d\nb交换后的值为：%d", a, b);
//	return 0;
//}

// 补充：
//自定义函数的形式参数如果定义的是数组，比如void main(int arr[],int k);这个形参arr数组接收的只是实参中的第一个元素的地址，并不是直接复制实参
//只能在主函数中算出数组的长度，自定义的函数再去调用.  但是仍可以在自定义函数的内部调用主函数中的数组的值
//无论这个形参中的数组是什么样的形式的定义，只能接收实参中数组的首元素的地址



//3.函数的调用的两种方式
//(1)传值调用：函数的形参和实参分别占用不同的内存块，对形参的修改不会影响实参

//(2)传址调用：
//把函数外部创建的变量的内存地址传递给函数参数的一种调用函数的方式
//这种传参方式可以让函数和函数外边的变量建立起真正的联系，也就是函数内部可以直接操作函数外部的变量。  比如传递数组

//printf()这个打印函数也会有返回值，返回值就是打印的字符的个数

//4.函数的声明和定义
// 这就是函数的模块化的过程
//(1)在主函数中想要调用add.c文件的函数，可以创建一个工程例如add.h，头文件的名字必须和函数所在的文件夹的名字相同
// //.h代表头文件的意思
//(2)在这个工程中放入add函数的声明 例如 int add(int x, int y);
//(3)在想要使用的文件中调用工程的说明就行，类似于调用头文件  include"add.h"

//链式访问：将一个函数的返回的函数值当做另一个函数的参数    sun(   add(1,2)   ,     7)

//补充：函数没用定义返回类型的时候，默认返回的是int类型    但是最好不要这样做

//函数是由函数签名部和函数体组成的，函数签名也就是函数体上面的所有东西



